package com.chuanke.ckfamily.action.finance;

import com.chuanke.ckfamily.action.BaseController;
import com.chuanke.ckfamily.action.base.Response;
import com.chuanke.ckfamily.dao.base.CkUtil;
import com.chuanke.ckfamily.dao.finance.model.GainPacket;
import com.chuanke.ckfamily.dao.finance.model.RedPacket;
import com.chuanke.ckfamily.dao.finance.model.RedPacketRule;
import com.chuanke.ckfamily.dao.social.model.Family;
import com.chuanke.ckfamily.dao.social.model.FamilyMember;
import com.chuanke.ckfamily.dao.user.model.User;
import com.chuanke.ckfamily.job.IncomeTask;
import com.chuanke.ckfamily.service.base.FailCode;
import com.chuanke.ckfamily.service.common.CacheService;
import com.chuanke.ckfamily.service.common.SysConfigService;
import com.chuanke.ckfamily.service.common.TipsService;
import com.chuanke.ckfamily.service.common.impl.RedisLockUtil;
import com.chuanke.ckfamily.service.constant.FamilyConstance;
import com.chuanke.ckfamily.service.constant.SysConfigKeyEnum;
import com.chuanke.ckfamily.service.exception.CFException;
import com.chuanke.ckfamily.service.finance.GainPacketService;
import com.chuanke.ckfamily.service.finance.RedPacketService;
import com.chuanke.ckfamily.service.finance.impl.RedPacketServiceImpl;
import com.chuanke.ckfamily.service.finance.vo.RedPacketInfo;
import com.chuanke.ckfamily.service.social.FamilyMemberService;
import com.chuanke.ckfamily.service.social.FamilyService;
import com.chuanke.ckfamily.service.user.UserService;
import com.chuanke.ckfamily.service.util.CkServerUtil;

import freemarker.template.TemplateException;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.async.WebAsyncTask;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;

@Api(tags = "红包", value = "红包相关的接口")
@RequestMapping("/api/redpacket")
@Controller
public class RedPacketControll extends BaseController{

    @Autowired
    private RedPacketService redPacketService;

    @Autowired
    private GainPacketService gainPacketService;

    @Autowired
    private FamilyService familyService;

    @Autowired
    private FamilyMemberService familyMemberService;

    @Autowired
    private TipsService tipsService;

    @Autowired
    private SysConfigService sysConfigService;

    @Autowired
    private CacheService cacheService;

    /**
     * <h1>创建家族红包</h1>
     *
     *
     *
     * @param request
     * @return
     */
    @ApiOperation(value = "创建家族红包", notes = "在点击红包进入家族红包页面调用的接口", httpMethod = "POST")
    @RequestMapping("/create_family_packet")
    @ResponseBody
    public Response createFamilyPacket(HttpServletRequest request) {
        Long uid = getUidByToken(request);
        Family family = null;
        Map<String, Object> result = new HashMap<>();

        long balance = 0l;
        try {
            result.put("rule", tipsService.getRedpackageRuleTips());
            result.put("rnote", RedPacketServiceImpl.DEFAULT_NOTE);

            family = familyService.getByOwner(uid);
            if (family != null && family.getBalance() != null) {
                balance = family.getBalance();
            }

            RedPacketRule rule = redPacketService.createFamilyPackate(uid);
            result.put("redpacket", rule);
            result.put("topTip", tipsService.getSendRedpackage(balance, rule.getPackatemoney(), rule.getPackatenum()));

        } catch (CFException e) {
            e.printStackTrace();
            result.put("redpacket", new RedPacketRule());
            result.put("topTip", e.getMsg());

        } catch (Exception e) {
            e.printStackTrace();
            result.put("redpacket", new RedPacketRule());
            result.put("topTip", e.getMessage());

        }

        return new Response(result);
    }

    /**
     * <h1>发送家族红包</h1>
     *
     * @param request
     * @return
     */
    @ApiOperation(value = "发送家族红包接口", notes = "点击创建家族红包调用的接口，发送红包到所有人", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "redpacket", value = "红包Id", required = true, dataTypeClass = Long.class),
            @ApiImplicitParam(name = "note", value = "红包内容", required = true, dataTypeClass = String.class)})
    @RequestMapping("/send_family_packet")
    @ResponseBody
    public Response sendFamilyPacket(HttpServletRequest request,
                                     @RequestParam("redpacket") Long rid,
                                     @RequestParam("note") String note) {
        try {
            Long uid = getUidByToken(request);
            redPacketService.sendFamilyPacket(uid, rid, note);
            return new Response("ok");

        } catch (CFException e) {
            e.printStackTrace();
            return new Response(e);

        } catch (Exception e) {
            e.printStackTrace();
            return new Response(FailCode.APP, e.getMessage());

        }
    }

    /**
     * <h1>创建族长红包</h1>
     *
     * @param request
     * @return
     */
    @ApiOperation(value = "创建族长红包", notes = "点击红包显示族长红包页面调用的接口", httpMethod = "POST")
    @RequestMapping("/create_leader_packet")
    @ResponseBody
    public Response createLeaderPacket(HttpServletRequest request) {
        Map<String, Object> result = new HashMap<>();
        try {
            Long uid = getUidByToken(request);
            RedPacket redPacket = redPacketService.createUserPackate(uid);
            Long balance = CkServerUtil.loadBalance(uid).getBalance();

            Integer fnum = sysConfigService.getIntegerValue(SysConfigKeyEnum.user_family_max.name(), FamilyConstance.FAMILY_CAPACITY);
            FamilyMember familyMember = familyMemberService.findByUserId(uid);
            Integer countMember = familyMemberService.searchCountByFamilyId(familyMember.getFamily_id());
            result.put("redpacket", redPacket);
            result.put("max_money", CkUtil.formateToYuan(balance));
            result.put("max_num", fnum);
            result.put("topTip", tipsService.getSendRedpackage(balance, countMember));

        } catch (CFException e) {
            e.printStackTrace();
            result.put("redpacket", new RedPacket());
            result.put("topTip", e.getMessage());

        } catch (Exception e) {
            e.printStackTrace();
            result.put("redpacket", new RedPacket());
            result.put("topTip", e.getMessage());

        }

        logger.debug("createLeaderPacket========>{}", result);
        return new Response(result);
    }

    /**
     * <h1>发送族长红包</h1>
     *
     * @param request
     * @param money
     * @param num
     * @return
     */
    @ApiOperation(value = "发送族长红包", notes = "点击创建红包显示族长红包页面调用的接口", httpMethod = "POST")
    @RequestMapping("/send_leader_packet")
    @ResponseBody
    public Response sendLeaderPacket (HttpServletRequest request,
                                      @RequestParam("money") Double money,
                                      @RequestParam("num") int num,
                                      @RequestParam("note") String note) {
        try {
            User user = getUserByToken(request);
            Long fmoney = new Double(money * 100).longValue();
            redPacketService.sendUserPacket(user.getId(), fmoney, num, note);
            return new Response("ok");

        } catch (CFException e) {
            e.printStackTrace();
            return new Response(e);

        } catch (Exception e) {
            e.printStackTrace();
            return new Response(e);

        }
    }

    /**
     * 领取红包
     *
     * @param request
     * @param pid
     * @return
     */
    @ApiOperation(value = "红包领取记录", notes = "红包领取记录详情接口", httpMethod = "POST")
    @ApiImplicitParam(name = "pid", value = "红包编号", required = true)
    @RequestMapping("/get_a_packet")
    @ResponseBody
    public WebAsyncTask pickupPacket(final HttpServletRequest request, @RequestParam("pid") final Long pid) {
        Callable<Response> callable = new Callable<Response>() {
            public Response call() throws Exception {
                logger.debug("begin get_a_packet=======>pid={}", pid);
                Long begin = System.currentTimeMillis();
                Long uid = getUidByToken(request);
                RedisLockUtil lockUtil = null;
        		try {
        			lockUtil = cacheService.getLock(CacheService.KEY_PREFIX.packetPickup_.name() + pid + "_" + uid);
                	
                    GainPacket gainPacket = gainPacketService.getAPacket(uid, pid);
                    return new Response(gainPacket);

                } catch (CFException e) {
                    return new Response(e);

                } finally {
                	if(lockUtil!=null){
                		lockUtil.unlock();
                	}

                    logger.info("pickupPacket =======>uid={},pid={},used={}", uid,pid,(System.currentTimeMillis() - begin));
                }
            }
        };

        return new WebAsyncTask(callable);
    }

    /**
     * 检查红包
     *
     * @param request
     * @param pid
     * @return
     */
    @ApiOperation(value = "检查红包是否领取过", notes = "点击聊天记录中的红包调用的接口", httpMethod = "POST")
    @ApiImplicitParam(name = "pid", value = "红包编号", required = true)
    @RequestMapping("/check")
    @ResponseBody
    public WebAsyncTask checkPacket(final HttpServletRequest request, final Long pid) {
        Callable<Response> callable = new Callable<Response>() {
            public Response call() throws Exception {
                Long begin = System.currentTimeMillis();
                Long uid = getUidByToken(request);
                try {
                    boolean hasGained = gainPacketService.hasGainedPacket(uid, pid);
                    return new Response(hasGained);

                } catch (CFException e) {
                    return new Response(e);

                } catch (Exception e) {
                    e.printStackTrace();
                    return new Response(FailCode.APP, e.getMessage());

                } finally {
                    logger.info("check packet ================>uid={},pid={},used = {}", uid,pid,(System.currentTimeMillis() - begin));
                }
            }
        };
        return new WebAsyncTask(callable);
    }

    /**
     * 获取红包记录
     *
     * @param request
     * @param pid
     * @return
     */
    @ApiOperation(value = "领取红包", notes = "点击红包开调用的接口", httpMethod = "POST")
    @ApiImplicitParam(name = "pid", value = "红包编号", required = true)
    @RequestMapping("/get_packet_records")
    @ResponseBody
    public Response getPacketRecords(HttpServletRequest request,
                                     @RequestParam("pid") Long pid) {
    	 Long begin = System.currentTimeMillis();
    	 Long uid = getUidByToken(request);
        try {
            RedPacketInfo packetInfo = gainPacketService.getRecords(uid, pid);
            return new Response(packetInfo);

        } catch (CFException e) {
            return new Response(e);

        } catch (Exception e) {
            e.printStackTrace();
            return new Response(FailCode.APP, e.getMessage());
        }finally{
       	 logger.info("get_packet_records ================>uid={},pid={},used = {}", uid,pid,(System.currentTimeMillis() - begin));
        }
    }

    /**
     * 获取领取红包的统计
     *
     * @param request
     * @return
     */
    @ApiOperation(value = "已领取的红包个数", httpMethod = "POST")
    @RequestMapping("/received_count")
    @ResponseBody
    public Response getReceivedCount(HttpServletRequest request) {
        try {
            Long uid = getUidByToken(request);
            Map<String, Object> result = new HashMap<>(2);
            result.put("num", gainPacketService.countHistory(uid));
            result.put("money", gainPacketService.sumHistory(uid));
            return new Response(result);

        } catch (Exception e) {
            e.printStackTrace();
            return new Response(FailCode.APP, e.getMessage());
        }
    }

    /**
     * 获取红包领取记录
     *
     * @param request
     * @param p
     * @return
     */
    @ApiOperation(value = "获取红包领取记录", httpMethod = "POST")
    @ApiImplicitParam(name = "p", value = "页码", required = false)
    @RequestMapping("/received_records")
    @ResponseBody
    public Response getReceivedRecords(HttpServletRequest request,
                                       @RequestParam(value = "p", required = false) Integer p) {
        try {
            if (p == null) {
                p = new Integer(0);
            }

            Long uid = getUidByToken(request);
            return new Response(gainPacketService.getHistory(uid, p));

        } catch (Exception e) {
            e.printStackTrace();
            return new Response(FailCode.APP, e.getMessage());

        }
    }

    @ApiOperation(value = "发送红包个数", httpMethod = "POST")
    @ApiImplicitParam(name = "p", value = "页码", required = false)
    @RequestMapping("/send_count")
    @ResponseBody
    public Response getSendCount(HttpServletRequest request,
                                 @RequestParam(value = "type", required = false) Integer type) {
        try {
            logger.debug("send count ========> type={}", type);
            Long uid = getUidByToken(request);
            Map<String, Object> result = new HashMap<>(3);
            result.put("num", redPacketService.countHistory(uid, type));
            result.put("money", redPacketService.sumHistory(uid, type));
            return new Response(result);

        } catch (CFException e) {
            e.printStackTrace();
            return new Response(e);

        } catch (Exception e) {
            e.printStackTrace();
            return new Response(FailCode.APP, e.getMessage());

        }
    }

    @ApiOperation(value = "发送红包记录", httpMethod = "POST")
    @ApiImplicitParam(name = "p", value = "页码", required = false)
    @RequestMapping("/send_records")
    @ResponseBody
    public Response getSendRecord(HttpServletRequest request,
                                  @RequestParam(value = "type", required = false) Integer type,
                                  @RequestParam(value = "p")Integer p) {
        try {
            Long uid = getUidByToken(request);
            if (p == null) {
                p = new Integer(0);
            }
            return new Response(redPacketService.findHistory(uid, type, p));

        } catch (CFException e) {
            e.printStackTrace();
            return new Response(e);

        } catch (Exception e) {
            e.printStackTrace();
            return new Response(FailCode.APP, e.getMessage());

        }
    }
}
